package analiseSintatica.Regras.Blocos;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Regra;
import analiseSintatica.estruturadados.NoArvore;

import java.util.LinkedList;

/**
 *
 * @author anderson
 * @date  6:42:13 PM
 */
public class RegraPrograma extends Regra {

    protected static Regra instancia;

    protected String estrutura = "<diretivas> <decls_inicial> void main '(' ')' <corpo_funcao> <decls_final>";
    
    /**
     * Construtor do singleton
     */
    private RegraPrograma() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraPrograma getInstance() {
        if (instancia == null) {
            instancia = new RegraPrograma();
        }
        return (RegraPrograma) instancia;

    }

    @Override
    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
    	
    	NoArvore terminalPrograma = new NoArvore("<programa>", false);

        if(RegraDiretivas.getInstance().getPrimeiro().contains(listaTokens.getFirst().getToken())){
    	try{

    		terminalPrograma.adicionaFilho(RegraDiretivas.getInstance().analisar(listaTokens));
    	}catch(ErroSintaticoException e){
    	    e.printStackTrace();
    	}
        }
        if(RegraDeclsInicial.getInstance().getPrimeiro().contains(listaTokens.getFirst().getToken())){
    	try{
    		terminalPrograma.adicionaFilho(RegraDeclsInicial.getInstance().analisar(listaTokens));
    	}catch(ErroSintaticoException e){
    		e.printStackTrace();
    	}
        }
    	
    	try {
    		terminalPrograma.adicionaFilho(reconheceToken(listaTokens, "void", estrutura));
        } catch (ErroSintaticoException e) {
        	e.printStackTrace();
        }
        
        try {
    		terminalPrograma.adicionaFilho(reconheceToken(listaTokens,"main", estrutura));
        } catch (ErroSintaticoException e) {
        	e.printStackTrace();
        }
        
        try {
        	terminalPrograma.adicionaFilho(reconheceLexema(listaTokens, "delimitador", "(", estrutura));
        } catch (ErroSintaticoException e) {
            e.printStackTrace();
        }
        
        try {
        	terminalPrograma.adicionaFilho(reconheceLexema(listaTokens, "delimitador", ")", estrutura));
        } catch (ErroSintaticoException e) {
            e.printStackTrace();
        }
        
        try{
    		terminalPrograma.adicionaFilho(RegraCorpoFuncao.getInstance().analisar(listaTokens));
    	}catch(ErroSintaticoException e){
    		e.printStackTrace();
    	}
    	
    	try{
            if(listaTokens.size()!=0)
    		terminalPrograma.adicionaFilho(RegraDeclsFinal.getInstance().analisar(listaTokens));
    	}catch(ErroSintaticoException e){
    		e.printStackTrace();
    	}
    	
        return terminalPrograma;

    }

    @Override
    protected void setPrimeiro() {

        this.primeiro.add("include");
        this.primeiro.add("typedef");
        this.primeiro.add("const");
        this.primeiro.add("char");
        this.primeiro.add("int");
        this.primeiro.add("float");
        this.primeiro.add("boolean");
        this.primeiro.add("void");
        this.primeiro.add("identificador");

        
//    	this.primeiro = RegraDiretivas.getInstance().getPrimeiro();
//    	primeiro.remove("e");
//    	primeiro = getUniao(primeiro, RegraDeclsInicial.getInstance().getPrimeiro());
//    	primeiro.remove("e");
//    	primeiro = getUniao(primeiro, "void");
    }

    @Override
    protected void setSeguinte() {
        this.seguinte.add("$");
       
    }
}
